'use strict';
const crypto = require('crypto');
const _ = require('lodash');

module.exports = app => {
  class SpaceService extends app.Service {
    /**
     * 创建机构，如果发现机构存在，返回错误信息，告知机构已经存在，不能创建
     * 如果机构不存在，那么就进行创建
     */
    * create(data) {
      let query;
      if (data && data.uid) {
        query = { uid: data.uid };
        delete data.uid;
      } else {
        return this.fail('must provide unique uid!');
      }

      const created = yield app.model.space.findOrCreate(query, data);
      if (created) {
        if (created.isNew === false) {
          return this.fail('space exist already! noted that uid for space must be unique.');
        }
        const newSpace = created.doc;

        // add default app
        const spaceConfig = newSpace.config || {};
        let appConfig = spaceConfig.app && spaceConfig.app.preload ? spaceConfig.app.preload : {};

        // add appEngine into space
        appConfig = Object.assign(appConfig, {
          appEngine: {
            name: 'appEngine',
            uid: 'appEngine',
            alias: 'App Engine',
            permits: [
              'as.admin', 'as.member', 'as.public', 'as.everyone',
            ],
          },
        });

        const apps = yield this.addManyApp(appConfig, newSpace);
        // add default roles,
        let preloadRoles = spaceConfig.role && spaceConfig.role.preloadRoles ? spaceConfig.role.preloadRoles : {};

        preloadRoles = Object.assign(preloadRoles, {
          admin: {
            uid: 'admin',
            name: 'admin',
            alias: 'admin',
          },
          member: {
            uid: 'member',
            name: 'member',
            alias: 'member',
          },
          public: {
            uid: 'public',
            name: 'public',
            alias: 'public',
          },
        });

        const defaultRoles = this.addManyRole(preloadRoles);

        // add current user into space with default role, default is public
        let defaultJoinRole = spaceConfig.role && spaceConfig.role.defaultJoinRole ? spaceConfig.role.defaultJoinRole : 'public';

        defaultJoinRole = this.getRole(defaultJoinRole, newSpace);

        this.ctx.service.role.addUser(this.ctx.service.user.getCurrent(), defaultJoinRole);

        // finally return newSpace
        return this.success(newSpace);
      }
      return this.fail('created space fail for unknown error!');
    }

    * findOne(filter) {
      const doc = yield app.model.space.findOne(filter);
      if (doc) {
        return this.success(doc);
      }
      return this.fail('fail to find space!');
    }

    * find(filter) {
      const docs = yield app.model.space.find(filter);
      return this.success(docs);
    }

    * addUserSpace(userData, spaceData) {
      const user = this.ctx.service.user.findOne(userData);
      const space = this.findOne(spaceData);

      if (user && space) {
        const role = space.getDefaultJoinRole();
        const added = this.ctx.service.role.addUser(user, role);
        if (added) {
          return this.success(added);
        }
        return this.fail('fail to add user into space!');

      }
      return this.fail('fail to find valid user or space!');

    }

    addRole(roleData, spaceData) {
      return this.ctx.service.role.create(roleData, spaceData);
    }

    * addManyRole(listOfRoleData, spaceData) {
      let space,
        added,
        listOfAdded;
      if (spaceData && spaceData._id) {
        space = spaceData;
      } else {
        space = yield app.model.space.findOne(spaceData);
        if (!(space && space._id)) {
          return this.fail('invalid space data!');
        }
      }

      if (_.isObject(listOfRoleData)) {
        for (const key in listOfRoleData) {
          const item = listOfRoleData[key];
          const added = yield this.addRole(item, spaceData);
          listOfAdded.push(added);
        }
        return this.success(listOfAdded);
      }
      return this.fail('invalid list of role data!');

    }

    * listRole(spaceData, filter = null) {
      const space = this.findOne(spaceData);
      if (space) {
        const roles = this.ctx.space.role.find({ space });
        return this.success(roles);
      }
      return this.fail('please provide valid space data!');
    }

    * listUserRole(userData, spaceData) {
      const user = this.ctx.service.user.findOne(userData);
      const space = this.findOne(userData);

      if (user && space) {
        const uRoles = app.model.userRole.find({
          user,
          space,
        });

        return this.success(uRoles);
      }
      this.fail('please provide valid user data and space data!');


    }

    /**
     * 将App添加到机构
     */
    * addApp(appData, spaceData) {
      let bApp,
        space,
        permits;

      if (!appData) {
        return this.fail('fail to find app data!');
      }

      if (!spaceData) {
        return this.fail('fail to find space data!');
      }

      if (appData._id) {
        bApp = appData;
      } else {
        if (appData.uid) {
          const findOrcreated = yield app.model.app.findOrCreate(appData);
          bApp = findOrcreated.doc;
        }
        if (bApp && appData.permits) {
          yield this.ctx.service.app.addManyPermit(appData.permits);
        }
      }

      if (spaceData._id) {
        space = spaceData;
      } else {
        if (spaceData.uid) {
          space = yield app.model.space.findOne({ uid: spaceData.uid });
          if (!space) {
            return this.fail('invalid space data!');
          }
        }
      }

      if (space._id && bApp._id) {
        const result = yield app.model.spaceApp.findOrCreate({ space: space._id, app: bApp._id });
        return this.success(result);
      }

      return this.fail('fail to create add app into space!');
    }

    /**
     * 同时添加多个应用
     */
    * addManyApp(listOfAppData, spaceData) {
      let space;
      const listOfAdded = [];
      if (spaceData._id) {
        space = spaceData;
      } else {
        space = yield app.model.space.findOne(spaceData);
        if (!(space && space._id)) {
          this.fail('please provide valid space data!');
        }
      }

      if (typeof listOfAppData === 'object') {
        for (const key in listOfAppData) {
          const item = listOfAppData[key];
          item.uid = key;
          const added = yield this.addApp(item, space);
          listOfAdded.push(added);
        }
      }

      return listOfAdded;
    }

    /**
     * 列出机构中的APP
     */
    * listApp() {

    }

    /**
     * 显示机构可以加的App的列表(在Appstore)里面，这个列表不能包括已经添加到机构的App
     */
    * listAppInStore() {

    }

    * listUserApp() {

    }
  }
  return SpaceService;
};
